package com.blog.cmrpersonalblog.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 密码工具类
 */
public class PasswordUtils {

    private static final String ALGORITHM = "SHA-256";
    private static final int SALT_LENGTH = 16;

    // 固定盐值前缀，用于生成用户特定的盐值
    private static final String SALT_PREFIX = "CMR_BLOG_2024_";

    // 全局固定盐值（可选方案）
    private static final String GLOBAL_SALT = "CMR_PERSONAL_BLOG_GLOBAL_SALT_2024";

    /**
     * 生成随机盐值
     * @return 盐值
     */
    public static String generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[SALT_LENGTH];
        random.nextBytes(salt);
        return Base64.getEncoder().encodeToString(salt);
    }

    /**
     * 加密密码
     * @param password 原始密码
     * @param salt 盐值
     * @return 加密后的密码
     */
    public static String encryptPassword(String password, String salt) {
        try {
            MessageDigest md = MessageDigest.getInstance(ALGORITHM);
            md.update(Base64.getDecoder().decode(salt));
            byte[] hashedPassword = md.digest(password.getBytes());
            return Base64.getEncoder().encodeToString(hashedPassword);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("密码加密失败", e);
        }
    }

    /**
     * 验证密码
     * @param password 原始密码
     * @param salt 盐值
     * @param encryptedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean verifyPassword(String password, String salt, String encryptedPassword) {
        String hashedPassword = encryptPassword(password, salt);
        return hashedPassword.equals(encryptedPassword);
    }

    /**
     * 简单MD5加密（用于兼容现有系统）
     * @param password 原始密码
     * @return MD5加密后的密码
     */
    public static String md5Encrypt(String password) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hashedPassword = md.digest(password.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : hashedPassword) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5加密失败", e);
        }
    }

    // ==================== 无数据库盐值的SHA-256方案 ====================

    /**
     * 方案1：基于用户名生成盐值的SHA-256加密
     * @param password 原始密码
     * @param userName 用户名
     * @return SHA-256加密后的密码
     */
    public static String sha256EncryptWithUserSalt(String password, String userName) {
        try {
            // 使用用户名 + 固定前缀生成盐值
            String userSalt = SALT_PREFIX + userName;
            MessageDigest md = MessageDigest.getInstance(ALGORITHM);
            md.update(userSalt.getBytes());
            byte[] hashedPassword = md.digest(password.getBytes());
            return Base64.getEncoder().encodeToString(hashedPassword);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256加密失败", e);
        }
    }

    /**
     * 方案2：使用全局固定盐值的SHA-256加密
     * @param password 原始密码
     * @return SHA-256加密后的密码
     */
    public static String sha256EncryptWithGlobalSalt(String password) {
        try {
            MessageDigest md = MessageDigest.getInstance(ALGORITHM);
            md.update(GLOBAL_SALT.getBytes());
            byte[] hashedPassword = md.digest(password.getBytes());
            return Base64.getEncoder().encodeToString(hashedPassword);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256加密失败", e);
        }
    }

    /**
     * 方案3：基于用户ID生成盐值的SHA-256加密
     * @param password 原始密码
     * @param userId 用户ID
     * @return SHA-256加密后的密码
     */
    public static String sha256EncryptWithUserIdSalt(String password, Long userId) {
        try {
            // 使用用户ID + 固定前缀生成盐值
            String userSalt = SALT_PREFIX + userId;
            MessageDigest md = MessageDigest.getInstance(ALGORITHM);
            md.update(userSalt.getBytes());
            byte[] hashedPassword = md.digest(password.getBytes());
            return Base64.getEncoder().encodeToString(hashedPassword);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256加密失败", e);
        }
    }

    /**
     * 验证密码（基于用户名的盐值）
     * @param password 原始密码
     * @param userName 用户名
     * @param encryptedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean verifyPasswordWithUserSalt(String password, String userName, String encryptedPassword) {
        String hashedPassword = sha256EncryptWithUserSalt(password, userName);
        return hashedPassword.equals(encryptedPassword);
    }

    /**
     * 验证密码（全局固定盐值）
     * @param password 原始密码
     * @param encryptedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean verifyPasswordWithGlobalSalt(String password, String encryptedPassword) {
        String hashedPassword = sha256EncryptWithGlobalSalt(password);
        return hashedPassword.equals(encryptedPassword);
    }

    /**
     * 验证密码（基于用户ID的盐值）
     * @param password 原始密码
     * @param userId 用户ID
     * @param encryptedPassword 加密后的密码
     * @return 是否匹配
     */
    public static boolean verifyPasswordWithUserIdSalt(String password, Long userId, String encryptedPassword) {
        String hashedPassword = sha256EncryptWithUserIdSalt(password, userId);
        return hashedPassword.equals(encryptedPassword);
    }
}
